﻿
using LxCFD;
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;


namespace TimeSolve
{
    public partial class MeshVM : BindableBase
    {
        public MeshVM()
        {
            initialize = new DelegateCommand<object>(_initialize);
            calculate = new DelegateCommand<object>(_calculate);
            calculateOnce = new DelegateCommand<object>(_calculateOnce);
            stop = new DelegateCommand<object>(_stop);
        }
        FvMesh mesh;
        public ObservableCollection<ZoneVM> zones { get; set; } = new ObservableCollection<ZoneVM>();
        public ObservableCollection<ContactVM> contacts { get; set; } = new ObservableCollection<ContactVM>();

        public int currentStep
        {
            get
            {
                return AppRes.StepsCenter.SteadyStep.StepsCount;
            }
            set
            {
                AppRes.StepsCenter.SteadyStep.StepsCount = value;
                RaisePropertyChanged("currentStep");
            }
        }

        public int maxStep
        {
            get
            {
                return AppRes.StepsCenter.SteadyStep.MaxSteps;
            }
            set
            {
                AppRes.StepsCenter.SteadyStep.MaxSteps = value;
                RaisePropertyChanged("maxStep");
            }
        }
        public bool isTransient
        {
            get
            {
                return AppRes.FvMesh.IsTransient;
            }
            set
            {
                AppRes.FvMesh.IsTransient = value;
                RaisePropertyChanged("isTransient");
            }
        }
        public bool isImplicit
        {
            get
            {
                return AppRes.FvMesh.TransientTimeSetting.IsImplicit;// mesh == null || mesh.transientTimeStore == null ? true : mesh.transientTimeStore.isImplicit;
            }
            set
            {
                AppRes.FvMesh.TransientTimeSetting.IsImplicit = value;
                RaisePropertyChanged("isImplicit");
            }
        }

        public double timeInterval
        {
            get
            {
                //return AppRes.PhysicalCenter.transientSetting.fixTimeInterval;
                if (AppRes .FvMesh .TransientTimeSetting is TransientTimeFixed tf)
                    return tf.FixInterval;
                else
                    return 0;
            }
            set
            {
                //AppRes.PhysicalCenter.transientSetting.fixTimeInterval = value;
                if (AppRes.FvMesh.TransientTimeSetting is TransientTimeFixed tf)
                    tf.FixInterval = value;
                else
                {
                    TransientTimeFixed ttf = new TransientTimeFixed() { FixInterval = value };
                    AppRes.FvMesh.TransientTimeSetting = ttf;
                }
                RaisePropertyChanged("timeInterval");
            }
        }
        public int maxTimeStep
        {
            get
            {
                return AppRes.StepsCenter.TransientStep.MaxSteps;
            }
            set
            {
                AppRes.StepsCenter.TransientStep.MaxSteps = value;
                RaisePropertyChanged("maxTimeStep");
            }
        }
        public DelegateCommand<object> initialize { get; set; }
        public DelegateCommand<object> calculate { get; set; }
        public DelegateCommand<object> calculateOnce { get; set; }
        public DelegateCommand<object> stop { get; set; }


        private void _initialize(object button)
        {
            AppRes.ComputeTask.RunForceInitialization();
        }
        private void _calculate(object button)
        {
            AppRes.ComputeTask.RunComputation();
        }
        private void _calculateOnce(object button)
        {

        }
        private void _stop(object button)
        {
            ComputeState.ReportInterrupt_ByUser();
        }
        public void LoadVMFromMesh(FvMesh mesh)
        {
            this.mesh = mesh;
            RaisePropertyChanged("currentStep");
            RaisePropertyChanged("maxStep");

            foreach (var z in mesh.Zones)
            {
                ZoneVM zvm = new ZoneVM(z);
                zones.Add(zvm);
            }
            foreach (var c in mesh.Contacts)
            {
                ContactVM cvm = new ContactVM(c);
                contacts.Add(cvm);
            }
            for (int i1 = 0; i1 < zones.Count; i1++)
            {
                for (int i2 = 0; i2 < zones[i1].BoundThreads.Count; i2++)
                {
                    FvContact con = mesh.Zones[i1].BoundThreads[i2].RootContact;
                    if (con != null)
                    {
                        zones[i1].BoundThreads[i2].inContact = contacts[con.ID];
                        if (con.OZone.ID == i1)
                        {
                            zones[i1].BoundThreads[i2].inContact.ownerZone = zones[i1];
                            zones[i1].BoundThreads[i2].inContact.ownerThread = zones[i1].BoundThreads[i2];
                        }
                        else
                        {
                            zones[i1].BoundThreads[i2].inContact.neighborZone = zones[i1];
                            zones[i1].BoundThreads[i2].inContact.neighborThread = zones[i1].BoundThreads[i2];
                        }
                    }
                }
            }
        }

    }

}
//public void ApplySetting()
//{
//    foreach (Zone z in zones)
//    {
//        FieldsBase_InZone.CheckFieldsAndApplySetting(z);
//    }
//    foreach (Contact c in contacts)
//    {
//        FieldsBase_OnBound.CheckFieldsAndApplySetting(c);
//    }
//}
//private void runCalculateOnce(int taskIndex)
//{
//    foreach (Zone z in zones)
//    {
//        z.fields.updateMatrix(taskIndex);
//        z.fields.solve(taskIndex);
//    }
//    MainViewModel.mainViewModel.log.AddWithTime(currentStep.ToString());
//    //foreach (Zone z in zones)
//    //{
//    //    double[] t = z.fields.getT();
//    //    foreach (Thread bt in z.BoundThreads)
//    //    {
//    //        double ave = 0;
//    //        for(int i1 = bt.ThreadIndex.StartCellIndex; i1 <= bt.ThreadIndex.EndCellIndex;i1++)
//    //        {
//    //            ave += t[i1];
//    //        }
//    //        Console.WriteLine("{0}:net--{1}", bt.name, ave / (bt.ThreadIndex.EndCellIndex - bt.ThreadIndex.StartCellIndex + 1));
//    //    }
//    //    //Console.WriteLine(z.name);
//    //    //Console.WriteLine("net--");
//    //    //Console.WriteLine(t.Average());
//    //}
//    IUpdataDisplay dis = MainViewModel.mainViewModel.selectedObject as IUpdataDisplay;
//    dis?.updatePartly();
//    currentStep++;
//}

//public void Initialize_ifNeeded(int taskIndex)
//{
//    foreach (Zone z in zones)
//    {
//        z.fields.initialize_ifNeeded(taskIndex);
//    }
//}
//public void Initialize_force(int taskIndex)
//{
//    foreach (Zone z in zones)
//    {
//        z.fields.initialize_force(taskIndex);
//    }
//}
//private void calTasks(int taskIndex)
//{
//    foreach (Zone z in zones)
//    {
//        z.fields.updateMatrix(taskIndex);
//        z.fields.solve(taskIndex);
//    }
//}

//private void hostTask_IniAndCal()
//{
//    hostTask_iniIfNeeded();
//    TasksControl.startNewCalTasks(calTasks, isContinue_bySteps);
//}
//private void hostTask_iniForce()
//{
//    currentStep = 0;
//    applySettingTask();
//    TasksControl.startNewCalTasks(iniTask_force);
//    isInitialized = true;
//}
//private void hostTask_iniIfNeeded()
//{
//    if (!isInitialized)
//    {
//        applySettingTask();
//        TasksControl.startNewCalTasks(iniTask_ifNeeded);
//        isInitialized = true;
//    }
//}
//private void hostTask_CalOnce()
//{
//    hostTask_iniIfNeeded();
//    TasksControl.startNewCalTasks(calTasks);
//}
//private void hostTask_clearFields()
//{
//    applySettingTask();
//    TasksController.startNewCalTasks(iniTask_force);
//    isInitialized = true;
//}
//if (!isInitialized)
//{
//    _initialize(null);
//}
//runCalculateOnce(1);
// TasksControler.startHostTask();
//if (!isInitialized)
//{
//    _initialize(null);
//}
//while (currentStep <maxStep)
//{
//    Console.WriteLine("=======当前步数：{0}=======",currentStep);
//    runCalculateOnce(1);
//}
//isInitialized = true;
//currentStep = 0;
//foreach (Zone z in zones)
//{
//    z.creatFieldsAndInitialize();
//}
//while (currentStep <maxStep)
//{
//    currentStep++;
//    Console.WriteLine("=======当前步数：{0}=======", currentStep);
//    TasksControler.startCalTasksAndWait();
//}
//public struct Cell
//{
//    public CellFace[] cellFaces;
//}
//public struct CellFace
//{
//    public CellFace (int threadInZone,int faceInThread)
//    {
//        this.threadInZone = threadInZone;
//        this.faceInThread = faceInThread;
//    }
//    public int threadInZone;
//    public int faceInThread;
//}

//public Zone coupledZone { get=>_coupledZone; set { _coupledZone = value;RaisePropertyChanged("coupledZone"); } }
//public Thread coupledThreaad { get=>_coupledThread; set { _coupledThread = value;RaisePropertyChanged("coupledThreaad"); } }